消除代码块中繁杂的if else

why

如果你的代码块中出现多 if else,往往意味着代码不便于维护,并有必要重构下代码了。本文提供几个小技巧,化解多 if else 的尴尬。

实例 1

1
2
3
4
5
6
7
8
9
var animalConsole = function(type) {
if (type === "fish") {
console.log("this is fish");
} else if (type === "bird") {
console.log("this is bird");
}
};

animalConsole("fish");

上述代码的问题在于扩展性极差,如果日后想再添加个 cat 就需要再来一个 if else,我们做个调整:

1
2
3
4
5
var animalConsole2 = function(type) {
console.log("this is " + type);
};

animalConsole2("fish");

这样修改之后代码做了简化,但有个问题 console 的文字格式要保持统一,失去了多样性,所以我们进一步调整:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var fish = {
console: function(){
console.log('我是小鱼儿')
}
}

var bird = {
console.log('我是鸟人,多多指教')
}

//多态
var animalConsole3 = function(animal){
animal.console()
}

animalConsole3(fish)
animalConsole3(bird)

上述代码使用了多态,扩展性变得更好,如果日后想增加个 cat,直接添加一个 cat 对象就可以了,不需要调整 animalConsole3 的代码。但是,也有个小的问题:代码有点松散,一共定义了三个对象。我们进一步调整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//策略模式
var animal = {
bird: function() {
console.log("我是鸟人哦");
},

fish: function() {
console.log("我是小鱼儿");
},

cat: function() {
console.log("我是可爱喵");
}
};

var animalConsole4 = function(animal, type) {
if (typeof animal[type] === "function") {
return animal[type]();
}
};

animalConsole4(animal, "bird");

上述代码使用了策略模式,所有的动物都挂在了 animal 对象上,日后 animal 对象可作为一个配置文件,便于扩展。

但是,上述代码中的 animal 参数有点多余,我们可以利用闭包将其去除:

1
2
3
4
5
6
7
8
9
10
11
var console5 = function(obj) {
return function consoleByType(type) {
if (typeof obj[type] === "function") {
return obj[type]();
}
};
};

var animalConsole5 = console5(animal);
animalConsole5("bird");
animalConsole5("fish");

相较于第一个版本,使用了多态和策略模式的代码就非常便于维护了。

实例 2

下面我们再看一个相对复杂的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function validate(data) {
if (data.username == "") {
return false;
}

if (data.password == "" || data.password.length < 8) {
return false;
}

if (data.description == "" || data.description.length < 20) {
return false;
}

return true;
}

上述是一个数据校验的代码,对上述代码进行重构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
var validator = {
hasValue: function(value) {
return typeof value === "string" && value !== "";
},

maxLength: function(value, max) {
return validator.hasValue(value) && value.length <= max;
}
};

function Validate() {
this.rules = [];
}

Validate.prototype.setData = function(data) {
this.data = data || {};
};

Validate.prototype.addRules = function(value, ruleType) {
var args = arguments;
ruleType = Array.prototype.splice.call(args, 1, 1)[0];
rules.push(
function() {
args[0] = this.data[args[0]];
return validator[ruleType].apply(null, args);
}.bind(this)
);
};

Validate.prototype.vali = function() {
for (var i = 0, len = this.rules.length; i < len; i++) {
if (!this.rules[i]()) {
return false;
}
}
return true;
};

//调用
var v = new Validate();

v.setData({
username: "alex",
password: "helloworld",
description: "nice boy"
});
v.addRules("username", "hasValue");
v.addRules("password", "maxLength", 8);
v.addRules("descriptoin", "maxLength", 20);

var result = v.vali();

进行重构之后,摒弃了多 if 代码,虽然代码量有所增加,但有利于后期维护。如果需要添加校验规则,则只需要填充 validator 对象和调用 addRules 即可。

总结

去除代码块中繁杂的 if else 逻辑的两个好用的方法:

  • 多态
  • 策略模式

日后还会补充。